from py2neo import Graph,Node,Relationship,NodeMatcher
from apps.neo4j.drawKnowledgeGraph import Draw
from apps.neo4j.gensim_train.train_result_api import gensim_handler


class Neo4j_Handle():

    graph = None

    matcher = None

    def __init__(self):
        pass

    def connectDB(self):
        self.graph = Graph("http://localhost:7474", auth = ("neo4j", "123456789"))
        self.matcher = NodeMatcher(self.graph)

    def initDB(self):

        print("Neo4j Init ...")
        # #Draw.graphClen(self.graph)
        #
        #
        # #Draw.delTheNode(self.graph, "ZongCheng")
        # #Draw.delTheNode(self.graph, "Phenomenon")
        #
        # # 创建 现象 结点
        # Draw.create_XianXiang_Node(self.graph)
        #
        #
        #
        # # 创建 总成 结点
        # Draw.create_ZC_Node(self.graph)
        #
        #
        # # 创建 故障原因 结点
        # Draw.create_Cause_of_Failure_Node(self.graph)
        #
        #
        # #创建 故障现象 -PointTo-> 总成 关系
        # Draw.Create_PointTo_Relation(self.graph)
        #
        #
        # #创建 故障现象 -Refer-> 故障原因 关系
        # Draw.Create_Refer_Relation(self.graph)
        print("Finished")


    # 对外界提供的接口


    # 根据现象显示所有
    def matchReasonByPhenomenon(self):

        s = "MATCH q=(p:Phenomenon) -[r:Refer]->(n:CauseOfFailure),(p)-[:PointTo]->(m) " \
            "RETURN m.Describe,p.Describe,p.Location,n"

        answer = self.graph.run(s).data()
        # answer = self.matchAllRelationJson()

        newlist = []

        # print(answer)

        for ele in answer:
            theList = list(ele.values())
            # print(theList)
            theList[3].update({"ZongCheng": theList[0]})
            theList[3].update({"Phenomenon": theList[1]})
            theList[3].update({"Phenomenon_Location": theList[2]})
            newlist.append(theList[3])

        # print(newlist)
        # print(len(newlist))
        return newlist

    def getLogicalTreeData(self):
        s = "MATCH a=(p:Phenomenon)-[r:PointTo]->(q),b=(p)-[s:Refer]->(m) return q.Describe as part,p.Location as child_part,m.Describe as fault"

        answer = self.graph.run(s).data()
        # print("dasdasd")
        return answer

    def getLogicalTreeData_ZongCheng(self,value):
        s = f"MATCH a=(p:Phenomenon)-[r:PointTo]->(q),b=(p)-[s:Refer]->(m) where q.Describe = '{value}' return q.Describe as part,p.Location as child_part,m.Describe as fault"
        answer = self.graph.run(s).data()
        # print("dasdasd")
        return answer


    def pyneo2j_ProblemNode_to_List(self,data):
        '''
        :param

            data:Node类型
        :return:

            dict(key,value)
        '''

        thedict = {}
        thedict["ProblemCode"] = data["ProblemCode"]
        thedict["Describe"] = data["Describe"]
        thedict["material"] = data["material"]
        thedict["method"] = data["method"]
        return thedict

    # 根据语义检索 返回(相似度，[现象名称，现象部位，原因，方法，材料])
    def matchReasonByPhenomenon_gensim(self, value):
        similar_results, max_record = gensim_handler.get_similarity(value)

        answer = []

        for i in range(max_record):

            s = f"MATCH q=(p:Phenomenon) -[r:Refer]->(n:CauseOfFailure) where p.Describe in {[similar_results[i][0]]} " \
                f"RETURN id(p), p.Describe,p.Location,n"

            newlist = []
            temp_answer = self.graph.run(s).data()
            for ele in temp_answer:
                theList = list(ele.values())
                theList[3].update({"id": theList[0]})
                theList[3].update({"Phenomenon": theList[1]})
                theList[3].update({"Phenomenon_Location": theList[2]})
                newlist.append(theList[3])
                # print(newlist)

            answer.append((similar_results[i][1], newlist))

        # print(answer)

        return answer

    # 节点关系添加
    def Node_Relation_Add(self, data=None):
        '''
        dict = {
            part (总成) :√
            phenomenon:√
            location: √
            cause:√
            material:√
            method:√
        }
        '''

        try:
            s1 = f"match (p:Phenomenon) where p.Describe = '{data['phenomenon']}' return p"
            s1_result = len(self.graph.run(s1).data())
            if s1_result == 0:
                self.graph.run(f"create (p:Phenomenon {{Describe: '{data['phenomenon']}' }})")

            s2 = f"match (z:ZongCheng) where z.Describe = '{data['part']}' return z"
            s2_result = len(self.graph.run(s2).data())
            if s2_result == 0:
                self.graph.run(f"create (z:ZongCheng {{Describe: '{data['part']}' }})")

            if s1_result == 0 or s2_result == 0:
                ss = f"match (p:Phenomenon),(z:ZongCheng) where p.Describe = '{data['phenomenon']}' and z.Describe = '{data['part']}' set p.Location = '{data['location']}' " \
                     f"create (p)-[:PointTo]->(z)"
                self.graph.run(ss)
            else:
                ss = f"match (p:Phenomenon),(z:ZongCheng) where p.Describe = '{data['phenomenon']}' and z.Describe = '{data['part']}' set p.Location = '{data['location']}' "
                self.graph.run(ss)

            s3 = f"match (f:CauseOfFailure) where f.Describe = '{data['cause']}' return f"
            s3_result = len(self.graph.run(s3).data())
            if s3_result == 0:
                ss = f"match (p:Phenomenon) where p.Describe = '{data['phenomenon']}' " \
                     f"create (f:CauseOfFailure {{Describe: '{data['cause']}',Material: '{data['material']}',Method: '{data['method']}'}}) " \
                     f"create (p)-[:Refer]->(f)"
                self.graph.run(ss)
            else:
                ss = f"match (f:CauseOfFailure) where f.Describe = '{data['cause']}' set f.Material = '{data['material']}',f.Method = '{data['method']}'"
                self.graph.run(ss)
            return 0
        except Exception as err:
            print(err)
            return 1

    # 找到所有的现象
    def matchAllPhenomenon(self):
        s = "MATCH (p:Phenomenon) RETURN p.Describe"
        dicList = self.graph.run(s).data()
        answer = [dicList[i]['p.Describe'] for i in range(len(dicList))]
        return answer

    # 找到所有的元素关系，封装成json传回前端
    def matchAllRelationJson(self):
        ###################################### 现象 - 原因 ###################################
        s = "MATCH q=(p:Phenomenon) -[r:Refer]->(n:CauseOfFailure) "\
            "RETURN id(p) as Pid, p.Describe, p.Location, id(r) as Rid, id(n) as Nid, n.Describe, n.Material, n.Method"

        answer = []
        dicList = self.graph.run(s).data()
        for i in range(len(dicList)):
            s = {}
            e = {}
            sp = {}
            ep = {}
            sp['name'] = dicList[i]['p.Describe']
            sp['Location'] = dicList[i]['p.Location']
            ep['name'] = dicList[i]['n.Describe']
            ep['Material'] = dicList[i]['n.Material']
            ep['Method'] = dicList[i]['n.Method']
            s['identity'] = dicList[i]['Pid']
            s['labels'] = ['Phenomenon']
            s['properties'] = sp
            e['identity'] = dicList[i]['Nid']
            e['labels'] = ['CauseOfFailure']
            e['properties'] = ep
            r = {}
            r['identity'] = dicList[i]['Rid']
            r['start'] = dicList[i]['Pid']
            r['end'] = dicList[i]['Nid']
            r['type'] = "Refer"
            r['properties'] = {"name": "原因"}
            seg = []
            seg_item = {}
            seg_item['start'] = s
            seg_item['end'] = e
            seg_item['relationship'] = r
            seg.append(seg_item)
            data_item = {}
            # data_item['start'] = s
            # data_item['end'] = e
            data_item['segments'] = seg
            # data_item['length'] = 1
            answer_item = {}
            answer_item['p'] = data_item
            answer.append(answer_item)

        ###################################### 现象 - 总成 ###################################
        s = "MATCH q=(p:Phenomenon) -[r:PointTo]->(n:ZongCheng) " \
            "RETURN id(p) as Pid, p.Describe, p.Location, id(r) as Rid, id(n) as Nid, n.Describe"

        dicList = self.graph.run(s).data()
        for i in range(len(dicList)):
            s = {}
            e = {}
            sp = {}
            ep = {}
            sp['name'] = dicList[i]['p.Describe']
            sp['Location'] = dicList[i]['p.Location']
            ep['name'] = dicList[i]['n.Describe']
            s['identity'] = dicList[i]['Pid']
            s['labels'] = ['Phenomenon']
            s['properties'] = sp
            e['identity'] = dicList[i]['Nid']
            e['labels'] = ['ZongCheng']
            e['properties'] = ep
            r = {}
            r['identity'] = dicList[i]['Rid']
            r['start'] = dicList[i]['Pid']
            r['end'] = dicList[i]['Nid']
            r['type'] = "PointTo"
            r['properties'] = {"name": "属于"}
            seg = []
            seg_item = {}
            seg_item['start'] = s
            seg_item['end'] = e
            seg_item['relationship'] = r
            seg.append(seg_item)
            data_item = {}
            # data_item['start'] = s
            # data_item['end'] = e
            data_item['segments'] = seg
            # data_item['length'] = 1
            answer_item = {}
            answer_item['p'] = data_item
            answer.append(answer_item)
        print(answer)
        return answer

    # 精确查询，给出数据库里存在的问题进行查询，返回对应的现象
    def exactSearch(self,pid):
        s = "MATCH q=(p:Phenomenon) -[r:Refer]->(n:CauseOfFailure) WHERE id(p)=" + pid + " RETURN p.Describe, id(n) as nid, n.Describe, n.Method"
        # print(s)
        dicList = self.graph.run(s).data()
        answer = []
        # (dicList[i]['n.Describe'], dicList[i]['n.Method'])
        for i in range(len(dicList)):
            item = {}
            content = {}
            content['id'] = dicList[i]['nid']
            content['reason'] = dicList[i]['n.Describe']
            content['method'] = dicList[i]['n.Method']
            item['id'] = int(pid)
            item['Phenomenon'] = dicList[i]['p.Describe']
            item['index'] = i + 1
            item['content'] = content
            # item['content'] = dicList[i]['n.Describe']
            answer.append(item)
        print(answer)
        return answer

    def details(self, pid, nid):
        # answer = {}
        answer = []

        s = "MATCH q=(p:Phenomenon) -[r:Refer]->(n:CauseOfFailure) WHERE id(n)="+ nid +" RETURN p.Describe, n.Describe, n.Method, n.Material"
        dicList = self.graph.run(s).data()
        # for i in range(len(dicList)):
        #     answer['pid'] = int(pid)
        #     answer['nid'] = int(nid)
        #     answer['reason'] = dicList[i]['n.Describe']
        #     answer['method'] = dicList[i]['n.Method']
        #     answer['material'] = dicList[i]['n.Material']
        answer.append({"key":"现象ID", "val":int(pid)})
        answer.append({"key":"现象", "val":dicList[0]['p.Describe']})
        answer.append({"key": "原因ID", "val": int(nid)})
        answer.append({"key":"原因", "val":dicList[0]['n.Describe']})
        answer.append({"key":"方法", "val":dicList[0]['n.Method']})
        answer.append({"key":"材料", "val":dicList[0]['n.Material']})

        s = "MATCH q=(p:Phenomenon) -[r:PointTo]->(z:ZongCheng) WHERE id(p)="+ pid +" RETURN p.Location, id(z) as zid, z.Describe"
        dicList = self.graph.run(s).data()
        # for i in range(len(dicList)):
        #     answer['zid'] = int(dicList[i]['zid'])
        #     answer['zongcheng'] = dicList[i]['z.Describe']
        #     answer['phenomenon'] = dicList[i]['p.Describe']
        #     answer['location'] = dicList[i]['p.Location']
        # return [answer]

        answer.append({"key":"总成ID", "val":dicList[0]['zid']})
        answer.append({"key":"总成", "val":dicList[0]['z.Describe']})
        answer.append({"key":"故障部位", "val":dicList[0]['p.Location']})
        return answer